package com.yuexunit.application.service;

import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import com.yuexunit.application.action.v1.model.UpdateInfo;
import com.yuexunit.application.entity.ApplicationEntity;
import com.yuexunit.application.entity.ApplicationVersionEntity;
import com.yuexunit.application.entity.PlatformEnum;
import com.yuexunit.core.exception.DuplicateException;
import com.yuexunit.core.exception.NotFoundException;
import com.yuexunit.inject.annotation.Implements;
import com.yuexunit.persist.PersistUtil;
import com.yuexunit.persist.annotation.Transactional;
import com.yuexunit.util.DateUtil;
import com.yuexunit.util.VersionUtil;


/**
 * @author wangjinshui
 */
@Implements(ApplicationService.class)
public class ApplicationServiceImpl implements ApplicationService {
	@Override
	@Transactional
	public Long createApplication(String name, String type, PlatformEnum platform, String director, String description) {
		ApplicationEntity entity = new ApplicationEntity(name, type, platform, director, description);
		PersistUtil.insert(entity);
		
		return entity.getApplicationId();
	}

	
	@Override
	public ApplicationEntity inquireApplication(Long appId) {
		ApplicationEntity entity = PersistUtil.get(ApplicationEntity.class, appId);
		
		if (appId == null) {
			throw new NotFoundException("应用不存在：" + appId);
		}
		
		return entity;
	}


	@Override
	public ApplicationEntity inquireApplication(String appKey) {
		DetachedCriteria cri = DetachedCriteria.forClass(ApplicationEntity.class);
		cri.add(Restrictions.eq("key", appKey));
		
		List<ApplicationEntity> entityList = PersistUtil.get(cri);
		if (entityList.size() == 0) {
			throw new NotFoundException("应用不存在：" + appKey);
		}
		if (entityList.size() >= 2) {
			throw new DuplicateException("应用重复定义：" + appKey);
		}
		
		return entityList.get(0);
	}


	@Override
	@Transactional
	public Long createApplicationVersion(ApplicationVersionEntity appVersion) {
		
		ApplicationEntity application = inquireApplication(appVersion.getApplicationId());
		
		// 若发现最新版本低于上一个版本的话，则拒绝。
		if (VersionUtil.compare(application.getLatestVersion(), appVersion.getLatestVersion()) >= 0) {
			throw new IllegalArgumentException("新增版本(" + appVersion.getLatestVersion() + ")的版本号太低，应大于之前的发布版本(" + application.getLatestVersion() + ")");
		}
		
		application.setLatestVersion(appVersion.getLatestVersion());
		if (appVersion.getForced()) {
			application.setLatestForcedVersion(appVersion.getLatestVersion());
		}
		PersistUtil.update(application);
		
		
		appVersion.setUpdateDate(DateUtil.now());
		PersistUtil.insert(appVersion);
		
		return appVersion.getApplicationVersionId();
	}

	public ApplicationVersionEntity inquireApplicationVersion(Long appId, String appVersion) {
		DetachedCriteria cri = DetachedCriteria.forClass(ApplicationVersionEntity.class);
		cri.add(Restrictions.eq("applicationId", appId))
			.add(Restrictions.eq("latestVersion", appVersion))
			;
		
		List<ApplicationVersionEntity> entityList = PersistUtil.get(cri);
		if (entityList.size() == 0) {
			throw new NotFoundException("应用版本不存在：" + appId + ", " + appVersion);
		}
		if (entityList.size() >= 2) {
			throw new DuplicateException("应用重复定义：" + appId + ", " + appVersion);
		}
		
		return entityList.get(0);
	}

	
	@Override
	public UpdateInfo checkForUpdate(String appKey, String appVersion) {
		ApplicationEntity application = inquireApplication(appKey);
		ApplicationVersionEntity latestVersion = inquireApplicationVersion(application.getApplicationId(), application.getLatestVersion());
		
		UpdateInfo updateInfo = new UpdateInfo();
		updateInfo.setLatestVersion(application.getLatestVersion());
		
		if (VersionUtil.compare(application.getLatestVersion(), appVersion) <= 0) {
			updateInfo.setUpgrade(0);
		} else if (VersionUtil.compare(application.getLatestForcedVersion(), appVersion) > 0) {
			updateInfo.setUpgrade(2);
		} else {
			updateInfo.setUpgrade(1);
		}
		updateInfo.setTitle(latestVersion.getLatestVersion());
		updateInfo.setContent(latestVersion.getContent());
		updateInfo.setDownloadUrl(latestVersion.getDownloadUrl());
		
		return updateInfo;
	}
}
